package com.example.ai.model.viewmodel

import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.snapshots.SnapshotStateList
import com.example.ai.Config
import com.example.ai.model.data.ChatRoomData
import com.example.ai.model.data.Identity
import com.example.ai.model.data.MessageData
import com.example.ai.model.data.MessageDatabase
import com.example.ai.model.data.MessageItem
import com.example.ai.model.source.HttpSource
import com.example.ai.model.source.HttpSourceNew
import com.example.ai.model.source.WSSource
import kotlinx.coroutines.async
import okhttp3.Response
import okhttp3.WebSocket
import okhttp3.WebSocketListener

/**
 * Created by lijinxi on 2024/3/7.
 * @Description:
 */
class MessageViewModel(
    private val chatRoom: ChatRoomData,
    private val database: MessageDatabase,
    private val wsSource: WSSource = WSSource(),
    private val httpSource: HttpSource = HttpSource(),
    private val httpSourceNew: HttpSourceNew = HttpSourceNew(),
    private val useNewSource: Boolean = false,
    private val saveToRoom: Boolean = true
) : BaseViewModel() {
    companion object {
        var DEFAULT_TALK_ID = "tlk_eWEd2Rr7vizZSySp4oYmv"
        var DEFAULT_TALK_URL =
            "https://d-id-talks-prod.s3.us-west-2.amazonaws.com/google-oauth2%7C107894760732312171469/tlk_OX_Yzz4toKyKQQ1syP30J/1710317742959.mp4?AWSAccessKeyId=AKIA5CUMPJBIK65W6FGA&Expires=1710404147&Signature=%2B7Zgnejpey4QipQfoUgF%2BXhRRwI%3D"
    }

    //设置WebSocket，创建时调用
    fun prepare() {
        wsSource.setWebSocketListener(object : WebSocketListener() {

            override fun onOpen(webSocket: WebSocket, response: Response) {
                super.onOpen(webSocket, response)
            }

            override fun onMessage(webSocket: WebSocket, text: String) {
                super.onMessage(webSocket, text)
                addMessage(MessageData(Identity.OTHER, text))
            }

            override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
                super.onFailure(webSocket, t, response)
                _netWorkError.value = true
            }

            override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
                super.onClosed(webSocket, code, reason)
            }
        })
        //从数据库中取出信息
        fetchRoomMessages()
    }

    private val _messages = mutableStateListOf<MessageData>()

    var messages: SnapshotStateList<MessageData> = _messages

    /**
     * @param index: 消息列表index
     */
    fun fetchVoice(index: Int) {
        val text = _messages[index].text
        safeRequest(text + index) {
            if (useNewSource) {
                async { httpSourceNew.fetchVoice(text = text) }.await()?.let {
                    //暂不考虑请求失败
                    _messages[index] = _messages[index].copy(audio = it.msg)
                }
            } else {
                async { httpSource.fetchVoice(text = text) }.await()?.let {
                    //暂不考虑请求失败
                    _messages[index] = _messages[index].copy(audio = it.msg)
                }
            }
        }
    }

    /**
     * @param index: 消息列表index
     */
    fun fetchTalkId(index: Int) {
        val audio = _messages[index].audio ?: return
        safeRequest(audio + index) {
            if (Config.DEBUG) {
                _messages[index] = _messages[index].copy(talkID = DEFAULT_TALK_ID)
            } else {
                if (useNewSource) {
                    async { httpSourceNew.fetchTalkID(audioUrl = audio) }.await()?.let {
                        if (it.msg.isEmpty()) {
                            fetchTalkId(index)
                        } else {
                            _messages[index] =
                                _messages[index].copy(talkID = it.msg.ifEmpty { DEFAULT_TALK_ID })
                        }
                    }
                } else {
                    async { httpSource.fetchTalkID(audioUrl = audio) }.await()?.let {
                        _messages[index] =
                            _messages[index].copy(talkID = it.msg.ifEmpty { DEFAULT_TALK_ID })
                    }
                }
            }
        }
    }

    /**
     * @param index: 消息列表index
     */
    fun fetchTalkUrl(index: Int) {
        val talkID = _messages[index].talkID ?: return
        safeRequest(talkID + index) {
            if (Config.DEBUG) {
                _messages[index] = _messages[index].copy(talkUrl = DEFAULT_TALK_URL)
            } else {
                if (useNewSource) {
                    async { httpSourceNew.fetchTalkUrl(talkID = talkID) }.await()?.let {
                        if (it.msg.isEmpty()) {
                            fetchTalkUrl(index)
                        } else {
                            //暂时不考虑这一步失败
                            _messages[index] =
                                _messages[index].copy(talkUrl = it.msg.ifEmpty { DEFAULT_TALK_URL })
                        }
                    }
                } else {
                    async { httpSource.fetchTalkUrl(talkID = talkID) }.await()?.let {
                        //暂时不考虑这一步失败
                        _messages[index] = _messages[index].copy(talkUrl = it.msg)
                    }
                }
            }
        }
    }

    fun addMessage(message: MessageData) {
        _messages.add(message)
        saveRoomMessages()
    }

    private fun fetchRoomMessages() {
        if (saveToRoom.not()) return
        safeRequest("fetch_room") {
            async { database.itemDao().fetchMessage(chatRoom.id) }.await()
                ?.let { messageItem ->
                    _messages.clear()
                    _messages.addAll(messageItem.messages)
                }
        }
    }

    private fun saveRoomMessages() {
        if (saveToRoom.not()) return
        safeRequest("save_room") {
            async {
                database.itemDao()
                    .insertMessage(
                        MessageItem(
                            chatRoom.id,
                            chatRoom.title,
                            _messages.toMutableList()
                        )
                    )
            }.await()
        }
    }

    fun chatRoomTitle(): String {
        return chatRoom.title
    }

    fun sendMessage(text: String) {
        safeRequest(text) {
            addMessage(MessageData(identity = Identity.MYSELF, text))
            if (useNewSource) {
                async { httpSourceNew.fetchChatText(message = text) }.await()?.let {
                    addMessage(MessageData(identity = Identity.OTHER, it.msg))
                }
            } else {
                wsSource.sendMessage(text)
            }
            if (Config.DEBUG) {
                //addMessage(MessageData(identity = Identity.OTHER, "Response:$text"))
            }
        }
    }

    fun close() {
        wsSource.closeWebSocket()
    }

    fun finalConsume() {
        ids.forEachIndexed { _, index ->
            _messages[index] = _messages[index].copy(consumed = true)
        }
        ids.clear()
    }

    private val ids = mutableListOf<Int>()
    fun preConsume(index: Int) {
        if (ids.contains(index)) return
        ids.add(index)
    }
}